/*
 *          File: queue.c
 *        Author: Robert I. Pitts <rip@cs.bu.edu>
 * Last Modified: March 9, 2000
 *         Topic: Queue - Array Implementation
 * ----------------------------------------------------------------
 */

#include <stdio.h>
#include <stdlib.h>
#include "slirp/queue.h"

/*
 * Constants
 * ---------
 * MAX_QUEUE_SIZE = Largest number of items queue can hold.
 */

#define MAX_QUEUE_SIZE 100

/*
 * struct queueCDT gives the implementation of a queue.
 * It holds the information that we need for each queue.
 */
typedef struct queueCDT {
        queueElementT contents[MAX_QUEUE_SIZE];
        int front;
        int count;
} queueCDT;

queueADT QueueCreate(void) {
        queueADT queue;

        queue = (queueADT)malloc(sizeof(queueCDT));

        if (queue == NULL) {
                fprintf(stderr, "Insufficient Memory for new Queue.\n");
                exit(ERROR_MEMORY); /* Exit program, returning error code. */
        }

        queue->front = 0;
        queue->count = 0;

        return queue;
}

void QueueDestroy(queueADT queue) { free(queue); }

void QueueEnter(queueADT queue, queueElementT element) {
        int newElementIndex;

        if (queue->count >= MAX_QUEUE_SIZE) {
                //    fprintf(stderr, "QueueEnter on Full Queue.\n");
                //    exit(ERROR_QUEUE);  /* Exit program, returning error code. */
                return;
        }

        /*
         * Calculate index at which to put
         * next element.
         */
        newElementIndex = (queue->front + queue->count) % MAX_QUEUE_SIZE;
        queue->contents[newElementIndex] = element;
        // printf("element %d, pointer to %d, [%s]\n",newElementIndex,element,element);

        queue->count++;
}

int QueuePeek(queueADT queue) { return queue->count; }

queueElementT QueueDelete(queueADT queue) {
        queueElementT oldElement;

        if (queue->count <= 0) {
                // fprintf(stderr, "QueueDelete on Empty Queue.\n");
                // exit(ERROR_QUEUE);  /* Exit program, returning error code. */
                return NULL;
        }

        /* Save the element so we can return it. */
        oldElement = queue->contents[queue->front];

        /*
         * Advance the index of the front,
         * making sure it wraps around the
         * array properly.
         */
        queue->front++;
        queue->front %= MAX_QUEUE_SIZE;

        // printf("dequing @%d [%s]\n",oldElement,oldElement);

        queue->count--;

        return oldElement;
}

int QueueIsEmpty(queueADT queue) { return queue->count <= 0; }

int QueueIsFull(queueADT queue) { return queue->count >= MAX_QUEUE_SIZE; }
